package admin

import (
	"OrgManager/app/models"
	"OrgManager/app/service"
	"OrgManager/library/response"
	"OrgManager/library/util"
	"database/sql"
	"fmt"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/os/gcache"
	"github.com/gogf/gf/os/glog"
	"github.com/gogf/gf/util/gconv"
	"sort"
	"strings"

	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
)

type SysController struct {
}

// 选项参数 struct
type OptionStruct struct {
	Name  string `json:"name"`
	Value int    `json:"value"`           // 不能设 omitempty ，因为 0 值被认为是空值，导致被忽略
	Key   string `json:"key,omitempty"`   // omitempty 表示生成json的时候忽略空值字段
	Tag   string `json:"tag,omitempty"`   // omitempty 表示生成json的时候忽略空值字段
	Color string `json:"color,omitempty"` // omitempty 表示生成json的时候忽略空值字段
	Icon  string `json:"icon,omitempty"`  // omitempty 表示生成json的时候忽略空值字段
}

func init() {
	var c = &SysController{} // 用户模块 路由注册 - 使用执行对象注册方式
	group := g.Server().Group("/admin/sys")
	group.ALL("/{pid}/show/sys_organ.bu", c.OrgDataListByPid)                       // 根据pid显示子组织机构列表
	group.ALL("/{pid}/show/sys_organ!no_member.bu", c.OrgDataListByPidAndNoMember)  // 根据pid显示子组织机构列表(仅显示公司及部门)
	group.ALL("/show/sys_organ!office_tree.bu", c.OrgDataOfficeTreeDataAndNoMember) // 根据pid显示子组织机构列表(仅显示公司及部门)
	group.ALL("/edit/sys_organ.bu", c.OrgDataSave)                                  // 对组织机构数据进行修改
	group.ALL("/{id}/edit/sys_organ!repassword.bu", c.OrgDataRepassword)            // 重置密码
	group.ALL("/edit_password.bu", c.EditPassword)                                  // 员工修改密码
	group.ALL("/edit/sys_organ!move_member.bu", c.OrgDataMoveMember)                // 移动员工至其它部门
	group.ALL("/get_option_params.bu", c.GetOptionParamsJsonData)                   // 获取选项参数数据
	group.ALL("/get_sys_menu.bu", c.GetSysMenuJsonData)                             // 获取系统菜单数据
	group.ALL("/edit/sys_role!save_all.bu", c.OrgRoleSaveAll)                       // 保存所有角色对应的权限
	group.ALL("/get_member_data.bu", c.GetMemberData)                               // 获取登录者的员工信息
	group.ALL("/show/sys_organ!search_member.bu", c.SearchMember)                   // 搜索员工信息
	group.ALL("/get_all_org_map.bu", c.GetAllOrgMap)                          			 // 获取所有机构（公司，部门）的map数据

}

// 根据PID获取下级组织机构数据
func (c *SysController) OrgDataListByPid(r *ghttp.Request) {

	glog.Infof(gconv.String(gcache.Get("testParams")))


	pid := r.GetInt("pid", 0)
	result, err := g.DB().Table("sys_organ").Where("pid = ?", pid).Select()

	if err == nil {
		// 如果错误等于空

		// 整理数据
		data := models.Data{}
		for _, value := range result {
			m := value.ToMap()
			if value["type"].Int() == service.SYS_ORGAN_TYPE_COMPANY || value["type"].Int() == service.SYS_ORGAN_TYPE_OFFICE {
				m["hasChildren"] = true
			}
			// 禁止传递密码至前端
			delete(m, "password")
			data = append(data, m)
		}

		// 对数据进行排序
		sort.Sort(data)

		// 如果读取不到数据
		response.Json(r, 1, "数据读取成功", data)
	} else if err == sql.ErrNoRows {
		// 如果读取不到数据
		response.Json(r, 0, "没有数据", result)
	} else {
		// 如果出错了
		glog.Error("错误:%v \r\n", err)
		response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
	}
}

// 根据PID获取下级组织机构数据(仅显示公司及部门)
func (c *SysController) OrgDataListByPidAndNoMember(r *ghttp.Request) {
	pid := r.GetInt("pid", 0)
	result, err := g.DB().Table("sys_organ").Where("pid = ? and status > 0 and type in (?)", pid, g.Slice{service.SYS_ORGAN_TYPE_COMPANY, service.SYS_ORGAN_TYPE_OFFICE}).Select()

	if err == nil {
		// 如果错误等于空

		// 整理数据
		data := models.Data{}
		for _, value := range result {
			m := value.ToMap()
			if value["type"].Int() == service.SYS_ORGAN_TYPE_COMPANY || value["type"].Int() == service.SYS_ORGAN_TYPE_OFFICE {
				m["hasChildren"] = true
			}
			// 禁止传递密码至前端
			delete(m, "password")
			data = append(data, m)
		}

		// 对数据进行排序
		sort.Sort(data)

		response.Json(r, 1, "数据读取成功", data)
	} else if err == sql.ErrNoRows {
		// 如果读取不到数据
		response.Json(r, 0, "没有数据", result)
	} else {
		// 如果出错了
		glog.Error("错误:%v \r\n", err)
		response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
	}
}

// 获取部门树形图数据
func (c *SysController) OrgDataOfficeTreeDataAndNoMember(r *ghttp.Request) {
	result, err := g.DB().Table("sys_organ").Where("status > 0 and type = ?", service.SYS_ORGAN_TYPE_OFFICE).Select()

	if err == nil {
		// 如果错误等于空

		// 向下递归，逐级添加至 data 中
		data := downAddItemAndSort(1, result)

		response.Json(r, 1, "数据读取成功", data)
	} else if err == sql.ErrNoRows {
		// 如果读取不到数据
		response.Json(r, 0, "没有数据", result)
	} else {
		// 如果出错了
		glog.Error("错误:%v \r\n", err)
		response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
	}
}

// 保存组织机构数据
func (c *SysController) OrgDataSave(r *ghttp.Request) {
	data, _ := r.GetJson()
	glog.Infof("读取到的数据:%v \r\n", data.ToMap())

	if _, exists := data.ToMap()["id"]; exists {
		// 如果存在ID，表示是修改数据。则清空密码字段
		delete(data.ToMap(), "password")
	} else {
		// 如果ID不存在的话表示新增员工，设置默认密码 147896325
		data.ToMap()["password"] = util.Md5ToMemberPassword("147896325")
	}

	if data.GetInt("type") == service.SYS_ORGAN_TYPE_MEMBER {
		// 如果是员工数据，则需要先判断员工是否存在
		member, err := g.DB().Table("sys_organ").Where("type = ? and phone = ?", service.SYS_ORGAN_TYPE_MEMBER, data.GetString("phone")).One()
		if err == nil {
			if member["id"].Int() == data.GetInt("id", 0) {
				// 如果手机号就是该员工本身的，则可继续保存
				result, err := g.DB().Table("sys_organ").Data(data.ToMap()).Save()
				if err == nil || err == sql.ErrNoRows {
					response.Json(r, 1, "数据修改成功", result)
				} else {
					glog.Error("错误:%v \r\n", err)
					response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
				}
			} else {
				response.Json(r, -1, fmt.Sprintf("操作失败：该手机号已被 [%s] 使用，请核对！", member["name"]), nil)
			}
		} else if err == sql.ErrNoRows {
			result, err := g.DB().Table("sys_organ").Data(data.ToMap()).Save()
			if err == nil || err == sql.ErrNoRows {
				response.Json(r, 1, "数据修改成功", result)
			} else {
				glog.Error("错误:%v \r\n", err)
				response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
			}
		} else {
			glog.Error("错误:%v \r\n", err)
			response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
		}
	} else if data.GetInt("type") == service.SYS_ORGAN_TYPE_OFFICE && data.GetInt("status") == -1 {
		_, err := g.DB().Table("sys_organ").Where("pid = ? and status > -1", data.GetInt("id")).All()
		if err == nil {
			response.Json(r, -3, "不能删除部门，请先删除下级部门及部门员工！", nil)
		} else if err == sql.ErrNoRows {
			result, err := g.DB().Table("sys_organ").Data(data.ToMap()).Save()
			if err == nil || err == sql.ErrNoRows {
				response.Json(r, 1, "数据修改成功", result)
			} else {
				glog.Error("错误:%v \r\n", err)
				response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
			}
		} else {
			glog.Error("错误:%v \r\n", err)
			response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
		}
	} else {
		// 如果是公司数据
		result, err := g.DB().Table("sys_organ").Data(data.ToMap()).Save()
		if err == nil || err == sql.ErrNoRows {
			response.Json(r, 1, "数据修改成功", result)
		} else {
			glog.Error("错误:%v \r\n", err)
			response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
		}
	}
}

// 重置组织机构密码
func (c *SysController) OrgDataRepassword(r *ghttp.Request) {
	id := r.GetInt("id", 0)
	if id > 0 {
		result, err := g.DB().Table("sys_organ").Data("password", util.Md5ToMemberPassword("147896325")).Where("id", id).Update()
		if err == nil || err == sql.ErrNoRows {
			response.Json(r, 1, "成功！密码已经重置为：147896325", result)
		} else {
			glog.Error("错误:%v \r\n", err)
			response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
		}
	} else {
		glog.Error("数据修改失败，缺少ID参数! \r\n", nil)
		response.Json(r, -2, "数据修改失败，缺少ID参数", nil)
	}
}

// 用户修改密码
func (c *SysController) EditPassword(r *ghttp.Request) {
	data, _ := r.GetJson()
	if data.GetString("oldPassword") != "" && data.GetString("newPassword1") != "" && data.GetString("newPassword2") != "" {
		if (data.GetString("newPassword1") == data.GetString("newPassword2")) {
			if r.Session.Contains(service.SESSION_KEY_MEMBER) {
				sessionMember := gconv.Map(r.Session.Get(service.SESSION_KEY_MEMBER))
				result, err := g.DB().Table("sys_organ").Where("id = ?", gconv.Int(sessionMember["id"])).One()
				if err == nil {
					if result["password"].String() == util.Md5ToMemberPassword(data.GetString("oldPassword")) {
						result["password"].Set(util.Md5ToMemberPassword(data.GetString("newPassword1")))
						_, err := g.DB().Table("sys_organ").Data(result).Where("id = ?", result["id"].Int()).Update()
						if err == nil || err == sql.ErrNoRows {
							response.Json(r, 1, "密码设置成功", result)
						} else {
							glog.Error("错误:%v \r\n", err)
							response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
						}
					} else {
						glog.Error("错误:%v \r\n", err)
						response.Json(r, -1, "修改失败：原密码错误，请重新输入！", nil)
					}
				} else if err == sql.ErrNoRows {
					glog.Error("错误:%v \r\n", err)
					response.Json(r, -1, "获取用户信息失败，请重新登录后再试！", nil)
				} else {
					glog.Error("错误:%v \r\n", err)
					response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
				}
			} else {
				response.Json(r, -1002, "您的登录信息已失效，请重新登录！", nil)
			}
		} else {
			response.Json(r, -3, "两次输入的新密码不一致！", nil)
		}
	} else {
		response.Json(r, -2, "参数丢失", nil)
	}
}

// 重置组织机构密码
func (c *SysController) OrgDataMoveMember(r *ghttp.Request) {
	data, _ := r.GetJson()
	memberId := data.GetInt("memberId", 0)
	tagOfficeId := data.GetInt("tagOfficeId", 0)

	if memberId > 0 && tagOfficeId > 0 {
		member, err := g.DB().Table("sys_organ").Where("id = ? ", memberId).One()
		if err == nil {
			if member["type"].Int() == service.SYS_ORGAN_TYPE_MEMBER {
				office, err := g.DB().Table("sys_organ").Where("id = ? ", tagOfficeId).One()
				if err == nil {
					if office["type"].Int() == service.SYS_ORGAN_TYPE_OFFICE {
						if member["tid"].Int() == office["tid"].Int() {
							member["pid"].Set(office["id"])
							result, err := g.DB().Table("sys_organ").Data(member.ToMap()).Save()
							if err == nil || err == sql.ErrNoRows {
								glog.Error("数据操作结果：%v \r\n", result)
								response.Json(r, 1, "移动成功", result)
							} else {
								glog.Error("错误:%v \r\n", err)
								response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
							}
						} else {
							response.Json(r, -1, "错误：只能在同一个公司之间进行移动！", err.Error())
						}
					} else {
						response.Json(r, -1, "错误：移动目标只能是部门！", err.Error())
					}
				} else if err == sql.ErrNoRows {
					response.Json(r, -1, "错误：获取目标部门信息失败！", err.Error())
				} else {
					glog.Error("错误:%v \r\n", err)
					response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
				}
			} else {
				response.Json(r, -1, "错误：只能对员工进行移动！", err.Error())
			}
		} else if err == sql.ErrNoRows {
			response.Json(r, -1, "错误：获取员工信息失败！", err.Error())
		} else {
			glog.Error("错误:%v \r\n", err)
			response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
		}
	} else {
		glog.Infof("移动失败，缺少ID参数! \r\n", nil)
		response.Json(r, -2, "移动失败，缺少ID参数", nil)
	}
}

// 获取选项参数数据
func (c *SysController) GetOptionParamsJsonData(r *ghttp.Request) {
	result, err := g.DB().Table("sys_option_params").Where("status > 0 ").OrderBy("pid desc, sort desc").All()
	if err == nil {
		// 遍历，获取所有父级数据

		data := make(map[string]interface{})

		for _, value := range result {
			if value["pid"].Int() == 0 {
				list := make([]OptionStruct, 0)
				for _, item := range result {
					if item["pid"].Int() == value["id"].Int() {
						s := OptionStruct{}
						s.Name = item["name"].String()
						s.Value = item["option_value"].Int()

						if len(item["option_key"].String()) > 0 {
							s.Key = item["option_key"].String()
						}

						if len(item["tag"].String()) > 0 {
							s.Tag = item["tag"].String()
						}

						if len(item["icon"].String()) > 0 {
							s.Icon = item["icon"].String()
						}

						if len(item["color"].String()) > 0 {
							s.Color = item["color"].String()
						}
						list = append(list, s)
					}
				}
				data[value["option_key"].String()] = list
			}
		}

		response.Json(r, 1, "读取数据成功", data)
	} else if err == sql.ErrNoRows {
		response.Json(r, 0, "数据为空", err.Error())
	} else {
		glog.Error("错误:%v \r\n", err)
		response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
	}
}

// 获取系统菜单数据
func (c *SysController) GetSysMenuJsonData(r *ghttp.Request) {
	if r.Session.Contains(service.SESSION_KEY_MEMBER) {
		orgMember := gconv.Map(r.Session.Get(service.SESSION_KEY_MEMBER))
		powerList := fmt.Sprintf("%s", orgMember["power_list"])

		result, err := g.DB().Table("sys_menu").Where("status > 0 ").All()
		if err == nil {
			// 遍历，获取所有父级数据

			// 整理数据
			data := models.Data{}
			for _, value := range result {
				if value["pid"].Int() == 0 {
					m := value.ToMap()

					children := models.Data{}
					for _, item := range result {
						if item["pid"].Int() == value["id"].Int() && strings.Contains(powerList, gconv.String(item["power"])) {
							children = append(children, item.ToMap())
						}
					}

					if children.Len() > 0 {
						sort.Sort(children)
						m["children"] = children

						data = append(data, m)
					}
				}
			}

			sort.Sort(data)

			response.Json(r, 1, "读取数据成功", data)
		} else if err == sql.ErrNoRows {
			response.Json(r, 0, "数据为空", err.Error())
		} else {
			glog.Error("错误:%v \r\n", err)
			response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
		}
	} else {
		response.Json(r, -1002, "您的登录信息已失效，请重新登录！", nil)
	}
}

// 保存角色数据
func (c *SysController) OrgRoleSaveAll(r *ghttp.Request) {
	data, _ := r.GetJson()
	var n int = 0
	for _, item := range data.ToArray() {
		_, err := g.DB().Table("sys_role").Data(item).Save()
		if err == nil || err == sql.ErrNoRows {
			n++
		}
	}

	if n > 0 {
		response.Json(r, 1, fmt.Sprintf("成功修改 %d 条数据！", n), nil)
	} else {
		response.Json(r, -1, "系统忙，请稍后再试！", data)
	}

}

// 获取登录者的员工信息
func (c *SysController) GetMemberData(r *ghttp.Request) {
	data := make(map[string]interface{})
	if r.Session.Contains(service.SESSION_KEY_MEMBER) {
		orgMember := gconv.Map(r.Session.Get(service.SESSION_KEY_MEMBER))
		data["name"] = orgMember["name"]
		response.Json(r, 1, "数据获取成功！", data)
	} else {
		response.Json(r, -1002, "您的登录信息已失效，请重新登录！", nil)
	}
}

// 获取登录者的员工信息
func (c *SysController) SearchMember(r *ghttp.Request) {
	data, _ := r.GetJson()

	glog.Infof("接受到的搜索参数:%v \r\n", data.ToMap())
	glog.Infof("数据大小:%d \r\n", len(data.ToMap()))

	if len(data.ToMap()) > 1 {

		m := make(map[int]gdb.Record, 0)

		result, err := g.DB().Table("sys_organ").Where(data.ToMap()).All()
		if err == nil {

			for _, item := range result {
				addUpItem(item["id"].Int(), m)
			}

			v := sortAddItem(0, m)

			glog.Infof("递归: %v \r\n", v)

			response.Json(r, 1, "查询成功", v)
		} else if err == sql.ErrNoRows {
			response.Json(r, 0, "数据为空", nil)
		} else {
			glog.Error("错误:%v \r\n", err)
			response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
		}
	} else {
		response.Json(r, 0, "搜索参数为空！", nil)
	}

}

// 获取所有机构的map数据 [id}json
func (c *SysController) GetAllOrgMap (r *ghttp.Request) {
	result, err := g.DB().Table("sys_organ").Where("type in (?)", g.Slice{service.SYS_ORGAN_TYPE_COMPANY, service.SYS_ORGAN_TYPE_OFFICE}).All();
	if err == nil {
		data := make(map[int]gdb.Record, 0)
		for _, item := range result {
			data[item["id"].Int()] = item
		}
		response.Json(r, 1, "数据查询成功", data)
	} else if err == sql.ErrNoRows {
		response.Json(r, 0, "数据为空", nil)
	} else {
		glog.Error("错误:%v \r\n", err)
		response.Json(r, -1, "系统忙，请稍后再试！", err.Error())
	}
}



// 向上递归，逐级添加上级部门入 map 中
func addUpItem(pid int, m map[int]gdb.Record) (int, map[int]gdb.Record) {
	result, err := g.DB().Table("sys_organ").Where("id = ?", pid).One()
	if err == nil {
		m[result["id"].Int()] = result
		if result["pid"].Int() > 0 {
			addUpItem(result["pid"].Int(), m)
		}
	}
	return 0, m
}

// 向下递归，排序并添加到 map 中
func sortAddItem(pid int, m map[int]gdb.Record) *models.Data {
	children := models.Data{}
	for _, value := range m {
		glog.Infof("-- %v \r\n", value.ToMap())
		if value["pid"].Int() == pid {
			item := value.ToMap()
			item["children"] = *sortAddItem(value["id"].Int(), m)
			children = append(children, item)
		}
	}
	sort.Sort(children)
	return &children
}

// 向下递归，排序并添加到 map 中
func downAddItemAndSort(pid int, data []gdb.Record) *models.Data {
	children := models.Data{}
	for _, value := range data {
		if value["pid"].Int() == pid {
			item := value.ToMap()
			item["children"] = *downAddItemAndSort(value["id"].Int(), data)
			children = append(children, item)
		}
	}
	sort.Sort(children)
	return &children
}
